package com.example.pay.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.pay.config.PayProperties;
import com.example.pay.entity.*;
import com.example.pay.mapper.*;
import com.example.pay.util.AesGcmUtil;
import com.example.pay.util.RsaSignUtil;
import com.example.pay.util.PemUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class NotifyService {
    private final PaymentTransactionMapper transactionMapper;
    private final MemberPackageItemMapper memberPackageItemMapper;
    private final MemberOrderMapper orderMapper;
    private final AddFriendMapper addFriendMapper;
    private final VipMapper vipMapper;
    private final PcLoginMapper pcLoginMapper;
    private final GroupAssistantMapper groupAssistantMapper;
    private final LuckyNumberMapper luckyNumberMapper;
    private final PayProperties payProperties;
    private final TUserMapper userMapper;
    private final UserPointsMapper userPointsMapper;
    private final UserPointsLogMapper userPointsLogMapper;
    private final TransactionTemplate transactionTemplate;
    private final PointsConfigDetailMapper pointsConfigDetailMapper;


    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 处理微信支付回调（v3）。
     * @param body 原始JSON字符串
     * @return 响应报文
     */
    public Map<String, Object> handleWeChatNotify(String body) {
        try {
            JsonNode root = objectMapper.readTree(body);
            JsonNode resource = root.path("resource");
            String cipherText = resource.path("ciphertext").asText();
            String nonce = resource.path("nonce").asText();
            String associatedData = resource.path("associated_data").asText(null);

            String plainText = AesGcmUtil.decryptToString(
                    payProperties.getWechat().getApiV3Key(),
                    nonce,
                    associatedData,
                    cipherText
            );

            JsonNode data = objectMapper.readTree(plainText);
            String orderCode = data.path("out_trade_no").asText();
            String transactionId = data.path("transaction_id").asText();
            String tradeState = data.path("trade_state").asText();

            PaymentTransaction tx = transactionMapper.selectOne(new QueryWrapper<PaymentTransaction>().eq("order_code", orderCode));
            MemberOrder order = orderMapper.selectOne(new QueryWrapper<MemberOrder>().eq("order_code", orderCode));
            if("SUCCESS".equals(tradeState)){
                log.info("微信回调支付成功");
            }
            if (tx != null) {
                tx.setTransactionId(transactionId);
                tx.setNotifyPayload(body);
                tx.setStatus("SUCCESS".equals(tradeState) ? 1 : 2);
                transactionMapper.updateById(tx);
            }
            if (order != null && "SUCCESS".equals(tradeState)) {
                order.setPayStatus(1);
                orderMapper.updateById(order);
                // 开通对应的业务权限
                createMemberPermissions(order);
            }
            Map<String, Object> resp = new HashMap<>();
            resp.put("code", "SUCCESS");
            resp.put("message", "OK");
            return resp;
        } catch (Exception e) {
            Map<String, Object> resp = new HashMap<>();
            resp.put("code", "ERROR");
            resp.put("message", e.getMessage());
            return resp;
        }
    }

    /**
     * 处理支付宝回调。
     * @param params form参数
     * @return 返回给支付宝的字符串：success/failure
     */
    public String handleAlipayNotify(Map<String, String> params) {
        String sign = params.get("sign");
        String signType = params.get("sign_type");
        // 构造待验签字符串：按键名升序，排除sign与sign_type，排除空值
        String contentToVerify = params.entrySet().stream()
                .filter(e -> !"sign".equals(e.getKey()) && !"sign_type".equals(e.getKey()))
                .filter(e -> e.getValue() != null && !e.getValue().isEmpty())
                .sorted(Map.Entry.comparingByKey())
                .map(e -> e.getKey() + "=" + e.getValue())
                .collect(Collectors.joining("&"));

        String alipayPublicKeyPem = PemUtil.loadPem(payProperties.getAlipay().getAlipayPublicKey());
        boolean pass = RsaSignUtil.verifySHA256withRSA(contentToVerify, sign, alipayPublicKeyPem);
        if (!pass) {
            return "failure";
        }

        String orderCode = params.getOrDefault("out_trade_no", "");
        String tradeNo = params.getOrDefault("trade_no", "");
        String tradeStatus = params.getOrDefault("trade_status", "");

        PaymentTransaction tx = transactionMapper.selectOne(new QueryWrapper<PaymentTransaction>().eq("order_code", orderCode));
        MemberOrder order = orderMapper.selectOne(new QueryWrapper<MemberOrder>().eq("order_code", orderCode));
        if("SUCCESS".equals(tradeStatus)){
            log.info("支付宝回调支付成功");
        }
        if (tx != null) {
            tx.setTransactionId(tradeNo);
            tx.setNotifyPayload(params.toString());
            if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                tx.setStatus(1);
            } else {
                tx.setStatus(2);
            }
            transactionMapper.updateById(tx);
        }
        if (order != null && ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus))) {
            order.setPayStatus(1);
            orderMapper.updateById(order);
            // 开通对应的业务权限
            createMemberPermissions(order);
        }
        return "success";
    }

    //生成对应会员权限数据
    public void createMemberPermissions(MemberOrder order) {
        log.info("原订单数据{}",order);
        // 获取对应的商品类型1加好友 2普通VIP 3高级VIP 4靓号 10001积分
        String productType = order.getProductType();
        if (productType == null) {
            log.warn("套餐类型不存在");
            return;
        }
        MemberPackageItem product = null;
        PointsConfigDetail detail = null;
        if ("10001".equals(order.getProductType())){
            // 获取积分套餐数据
            detail = pointsConfigDetailMapper.selectById(order.getProductId());
            if (detail == null) {
                log.warn("未找到商品");
                throw new RuntimeException("未找到商品");
            }
        }else {
            // 获取商品信息
            product = memberPackageItemMapper.selectOne(new LambdaQueryWrapper<MemberPackageItem>().eq(MemberPackageItem::getItemId,order.getProductId()));
            if (product == null) {
                log.warn("未找到商品");
                throw new RuntimeException("未找到商品");
            }
        }
        QueryWrapper<TUser> wrapper = new QueryWrapper<>();
        wrapper.select("id,_mobile,_display_name");
        wrapper.eq("_uid",order.getUserId());
        TUser tUser = userMapper.selectOne(wrapper);
        switch (productType) {
            // 判断当前用户权限最后一个月时是否过期，过期则在最后一个月权限基础上延长，否则创建新权限
            case "3":
                // 群助手权限
                createNormalVipPermission(order, product,tUser);
                break;
            case "2":
                // pc端权限
                createAdvancedVipPermission(order, product,tUser);
                break;
            case "4":
                // 靓号ID
                createLuckyNumberPermission(order, product,tUser);
                break;
            case "1":
                // 加好友
                createAddFriendPermission(order, product,tUser);
                break;
            case "5":
                // vip
                createVipPermission(order, product,tUser);
                break;
            case "10001":
                // 积分订单
                createPoints(order, detail,tUser);
                break;
            default:
                log.warn("未知商品类型: {}", productType);
                break;
        }
    }

    private void createVipPermission(MemberOrder order, MemberPackageItem product, TUser user) {
        String ownerId = order.getUserId();
        if (ownerId == null) {
            log.warn("加好友权限创建失败：缺少用户ID");
            return;
        }
        Vip last = vipMapper.selectOne(new QueryWrapper<Vip>()
            .eq("owner_id", ownerId)
            .orderByDesc("end_time")
            .last("limit 1"));
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime baseStart = (last != null && last.getEndTime() != null && last.getEndTime().isAfter(now))
            ? last.getEndTime() : now;
        LocalDateTime end = addPeriod(baseStart, product.getTimePeriod(), product.getPeriodUnit());

        Vip af = new Vip();
        af.setOwnerId(ownerId);
        af.setStartTime(baseStart);
        af.setEndTime(end);
        af.setCreateTime(LocalDateTime.now());
        af.setPhone(user.getMobile());
        af.setUserName(user.getDisplayName());
        af.setOrderNo(order.getOrderCode());
        vipMapper.insert(af);
        log.info("已为用户{}创建加好友权限：{} 至 {}", ownerId, baseStart, end);
    }

    private void createPoints(MemberOrder order, PointsConfigDetail detail, TUser tUser) {
        // 生成积分操作记录
        UserPointsLog userPointsLog = new UserPointsLog();
        userPointsLog.setCreatedAt(LocalDateTime.now());
        userPointsLog.setUid(order.getUserId());
        userPointsLog.setUserName(tUser.getDisplayName());
        userPointsLog.setMobile(tUser.getMobile());
        userPointsLog.setOperateType(1); // 1新增
        userPointsLog.setPoints(detail.getPoints());
        userPointsLog.setSourceType(1); // 1充值
        userPointsLog.setOrderId(String.valueOf(order.getId()));
        userPointsLog.setUpdatedAt(LocalDateTime.now());
        userPointsLog.setPaymentMethods(order.getPurchaseType());
        // 添加用户总积分
        // 判断是否有该用户积分记录
        UserPoints userPoints = new UserPoints();
        userPoints.setUid(order.getUserId());
        UserPoints u = userPointsMapper.selectOne(new LambdaQueryWrapper<UserPoints>().eq(UserPoints::getUid, tUser.getUid()));
        transactionTemplate.execute(e->{
            userPointsLogMapper.insert(userPointsLog);
            if (u == null) {
                // 新增用户积分记录
                userPoints.setTotalPoints(detail.getPoints());
                userPoints.setAvailablePoints(detail.getPoints());
                userPoints.setUserName(tUser.getDisplayName());
                userPoints.setMobile(tUser.getMobile());
                userPoints.setCreatedAt(LocalDateTime.now());
                userPoints.setUpdatedAt(LocalDateTime.now());
                userPointsMapper.insert(userPoints);
            } else {
                // 更新用户积分记录
                u.setTotalPoints(u.getTotalPoints() + detail.getPoints());
                u.setAvailablePoints(u.getAvailablePoints() + detail.getPoints());
                u.setUpdatedAt(LocalDateTime.now());
                userPointsMapper.updateById(u);
            }
            return true;
        });
    }

    /**
     * 创建加好友权限
     * @param order 订单
     * @param product 商品
     */
    private void createAddFriendPermission(MemberOrder order, MemberPackageItem product,TUser user) {
        String ownerId = order.getUserId();
        if (ownerId == null) {
            log.warn("加好友权限创建失败：缺少用户ID");
            return;
        }
        AddFriend last = addFriendMapper.selectOne(new QueryWrapper<AddFriend>()
                .eq("owner_id", ownerId)
                .orderByDesc("end_time")
                .last("limit 1"));
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime baseStart = (last != null && last.getEndTime() != null && last.getEndTime().isAfter(now))
                ? last.getEndTime() : now;
        LocalDateTime end = addPeriod(baseStart, product.getTimePeriod(), product.getPeriodUnit());

        AddFriend af = new AddFriend();
        af.setOwnerId(ownerId);
        af.setStartTime(baseStart);
        af.setEndTime(end);
        af.setCreateTime(LocalDateTime.now());
        af.setPhone(user.getMobile());
        af.setUserName(user.getDisplayName());
        af.setOrderNo(order.getOrderCode());
        addFriendMapper.insert(af);
        log.info("已为用户{}创建加好友权限：{} 至 {}", ownerId, baseStart, end);
    }
    /**
     * 创建靓号ID权限
     * @param order 订单
     * @param product 商品
     */
    private void createLuckyNumberPermission(MemberOrder order, MemberPackageItem product,TUser user) {
        String phone = user.getMobile();
        if (phone == null || phone.isEmpty()) {
            log.warn("靓号ID权限创建失败：缺少用户手机号");
            return;
        }
        // 先将该用户现有记录标记为失效（status = -1）
        LuckyNumber updateEntity = new LuckyNumber();
        updateEntity.setStatus(-1);
        luckyNumberMapper.update(updateEntity, new QueryWrapper<LuckyNumber>()
                .eq("phone_number", phone));

        // 新增一条有效记录（status = 1）
        LocalDateTime now = LocalDateTime.now();
        LuckyNumber ln = new LuckyNumber();
        ln.setUserId(order.getUserId());
        ln.setUsername(user.getDisplayName());
        ln.setPhoneNumber(user.getMobile());
        ln.setPackageName(product.getItemDesc());
        ln.setPurchaseTime(now);
        ln.setCreateTime(LocalDateTime.now());
        ln.setStatus(1);
        ln.setOrderNo(order.getOrderCode());
        luckyNumberMapper.insert(ln);
        log.info("已为用户{}创建靓号记录：套餐={}, 购买时间={} 状态=1", order.getUserId(), "靓号会员", now);
    }
    /**
     * 创建高级VIP权限
     * @param order 订单
     * @param product 商品
     */
    private void createAdvancedVipPermission(MemberOrder order, MemberPackageItem product,TUser user) {
        String phone = user.getMobile();
        if (phone == null || phone.isEmpty()) {
            log.warn("PC权限创建失败：缺少用户手机号");
            return;
        }
        PcLogin last = pcLoginMapper.selectOne(new QueryWrapper<PcLogin>()
                .eq("user_phone", phone)
                .orderByDesc("end_time")
                .last("limit 1"));
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime lastEnd = null;
        if (last != null){
            if (last.getEndTime() != null && !last.getEndTime().isEmpty()){
                lastEnd = LocalDate.parse(last.getEndTime(), fmt).atStartOfDay();
            }
        }
        LocalDateTime baseStart = (lastEnd != null && lastEnd.isAfter(now)) ? lastEnd : now;
        LocalDateTime end = addPeriod(baseStart, product.getTimePeriod(), product.getPeriodUnit());
        PcLogin rec = new PcLogin();
        rec.setUserPhone(phone);
        rec.setStatus(1);
        rec.setStartTime(baseStart.format(fmt));
        rec.setEndTime(end.format(fmt));
        rec.setCreateTime(LocalDateTime.now());
        rec.setOwnerId(order.getUserId());
        rec.setOrderNo(order.getOrderCode());
        pcLoginMapper.insert(rec);
        log.info("已为手机号{}创建PC登录权限：{} 至 {}", phone, baseStart, end);
    }
    /**
     * 创建普通VIP权限
     * @param order 订单
     * @param product 商品
     */
    private void createNormalVipPermission(MemberOrder order, MemberPackageItem product,TUser user) {
        if (user == null) {
            log.warn("群助手权限创建失败：缺少用户ID");
            return;
        }
        Long ownerId = user.getId();
        GroupAssistant last = groupAssistantMapper.selectOne(new QueryWrapper<GroupAssistant>()
                .eq("owner_id", ownerId)
                .orderByDesc("end_time")
                .last("limit 1"));
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime baseStart = (last != null && last.getEndTime() != null && last.getEndTime().isAfter(now))
                ? last.getEndTime() : now;
        LocalDateTime end = addPeriod(baseStart, product.getTimePeriod(), product.getPeriodUnit());

        GroupAssistant ga = new GroupAssistant();
        ga.setOwnerId(ownerId);
        ga.setStartTime(baseStart);
        ga.setEndTime(end);
        ga.setCreateTime(LocalDateTime.now());
        ga.setOrderNo(order.getOrderCode());
        groupAssistantMapper.insert(ga);
        log.info("已为用户{}创建群助手权限：{} 至 {}", ownerId, baseStart, end);
    }

    private LocalDateTime addPeriod(LocalDateTime start, Integer timePeriod, String unit) {
        if (timePeriod == null || unit == null) {
            return start;
        }
        switch (unit.toUpperCase(Locale.ROOT)) {
            case "DAY":
                return start.plusDays(timePeriod);
            case "MONTH":
                return start.plusMonths(timePeriod);
            case "YEAR":
                return start.plusYears(timePeriod);
            default:
                return start.plusDays(timePeriod);
        }
    }

}
